/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
 * secGear is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <linux/limits.h>

#include "enclave.h"
#include <string>
#include "sqlite3_u.h" // Headers for untrusted part (autogenerated by edger8r)

using namespace std;


// ocalls for printing string (C++ ocalls)
void ocall_print_error(const char *str){
    cerr << str << endl;
}

void ocall_print_string(const char *str){
    cout << str;
}

void ocall_println_string(const char *str){
    cout << str << endl;
}

// Application entry
int main(int argc, char *argv[]){
    if ( argc != 2 ){
        cout << "Usage: " << argv[0] << " <database>" << endl;
        return -1;
    }
    const char* dbname = argv[1];

    int retval = 0;
    cc_enclave_t global_eid = {};   
    cc_enclave_result_t res = CC_FAIL;                  // enclave状态结果
    char *path = PATH;

    string input;

    char real_p[PATH_MAX];
    /* check file exists, if not exist then use absolute path */
    if (realpath(path, real_p) == NULL) {
        if (getcwd(real_p, sizeof(real_p)) == NULL) {
            printf("Cannot find enclave.sign.so");
            return res;
        }
        if (PATH_MAX - strlen(real_p) <= strlen("/enclave.signed.so")) {
            printf("Failed to strcat enclave.sign.so path");
            return res;
        }
        (void)strcat(real_p, "/enclave.signed.so");
    }
    // 创建飞地
    res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &global_eid);
    if (res != CC_SUCCESS) {
        printf("host create enclave error\n");
        goto end; 
    }
    printf("host create enclave success\n");
    cout << "Info: SQLite SGX enclave successfully created." << endl;

    // Open SQLite database
    res = ecall_opendb(&global_eid, dbname);    // 返回值为void的函数不需要将返回值指针作为参数传入
    cout << "res: " << res << endl; 
    if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
        cerr << "Error: Making an ecall_open()" << endl;
        goto end;
    }
    cout << "Enter SQL statement to execute or 'quit' to exit: " << endl;

    cout << "> ";
    while(getline(cin, input)) {
        if (input == "quit"){
            break;
        }
        const char* sql = input.c_str();
        res = ecall_execute_sql(&global_eid, sql); 
        if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
            cerr << "Error: Making an ecall_execute_sql()" << endl;
            goto end;
        }
        cout << "> ";
    }

    // Closing SQLite database inside enclave
    res = ecall_closedb(&global_eid);
    if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
        cerr << "Error: Making an ecall_closedb()" << endl;
        goto end;
    }

    // Destroy the enclave
    res = cc_enclave_destroy(&global_eid);
    if (res != CC_SUCCESS) {
        cerr << "Error: destroying enclave" << endl;
        goto end;
    }
    cout << "Info: SQLite SGX enclave successfully returned." << endl;

end:
    return 0;
}
